package com.test.demo.statemachine.config;

import com.test.demo.statemachine.enums.MyEvent;
import com.test.demo.statemachine.enums.MyState;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.Message;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.listener.StateMachineListener;
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
import org.springframework.statemachine.state.State;
import org.springframework.statemachine.transition.Transition;

import java.util.EnumSet;
import java.util.Objects;

/**
 * @ClassName MyStateMachineConfig
 * @Description
 * @Author laigl
 * @Date 2020/4/22 10:50
 **/
@Configuration
@EnableStateMachine
public class MyStateMachineConfig extends EnumStateMachineConfigurerAdapter<MyState, MyEvent> {

    @Override
    public void configure(StateMachineStateConfigurer<MyState, MyEvent> states) throws Exception {
        states.withStates()
                .initial(MyState.SI)
                .states(EnumSet.allOf(MyState.class));
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<MyState, MyEvent> transitions) throws Exception {
        transitions.withExternal()
                .source(MyState.SI).target(MyState.S1).event(MyEvent.E1)
                .and()
                .withExternal()
                .source(MyState.S1).target(MyState.S2).event(MyEvent.E2)
                .and()
                .withExternal()
                .source(MyState.S2).target(MyState.S3).event(MyEvent.E3);
    }

    @Override
    public void configure(StateMachineConfigurationConfigurer<MyState, MyEvent> config) throws Exception {
        config.withConfiguration()
                .autoStartup(true)
                .listener(listener());
    }

    private StateMachineListener<MyState, MyEvent> listener() {
        return new StateMachineListenerAdapter<MyState, MyEvent>() {

            @Override
            public void transition(Transition<MyState, MyEvent> transition) {
                System.out.println("move from:{" + transition.getSource() + "} " +
                        "to:{" + transition.getTarget() + "}");
            }

            @Override
            public void stateChanged(State<MyState, MyEvent> from, State<MyState, MyEvent> to) {
                if (Objects.nonNull(from)) {
                    System.out.println("State change from " + from.getId() + " to " + to.getId());
                } else {
                    System.out.println("State change to " + to.getId());
                }
            }

            @Override
            public void eventNotAccepted(Message<MyEvent> event) {
                System.out.println("event not accepted: {" + event + "}");
            }

        };
    }

}
